#ifndef __AVPACKET_QUEUE_H__
#define __AVPACKET_QUEUE_H__

#include <unistd.h>
#include <sys/mman.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <memory.h>

#include <stdint.h>
#include <stdbool.h>
#include <time.h>

#ifdef __cplusplus
extern "C"
{
#endif

#define ECONDER_EXTRA_DATA_LEN 512
    /*
    * encoder_extra 记录了编码器的额外信息，SPS, PPS
    *
    */
    typedef struct encoder_extra
    {
        uint8_t* data; //需要动态分配 512 字节，用于保存编码器SPS和PPS等额外信息 
        int  len;
    } encoder_extra_t;


    /*
    * encoder_param:
    * 编码器参数数据结构
    */
    typedef struct encoder_param
    {
        int type;  // 视频编码方式, H264: 0; H265:1
        int width;
        int height;
        int frame_rate;
        int bitrate;
    } encoder_param_t;

    /*
     * encoder_info:
     * 编码器数据结构
     *
    */
    typedef struct encoder_info
    {
        encoder_param_t encoder_param;
        encoder_extra_t encoder_extra;
    } encoder_info_t;

    /*
     * avpaket_info:
     * 视频编码数据结构
     *
    */
    typedef struct avpacket_info
    {
        void* data;  // 数据存储区
        int data_len;   // 数据长度
        int rd_index; // 当前读指针位置
        int type;       // 视频编码方式, H264: 0; H265:1
        int iframe;   // 贞的类别，是否为 I 贞， 1 表示当前包是 I 贞， 0 则不是
        unsigned long long ts; // 时间戳:单位 微妙
        unsigned long long sn; // 序列码
    } avpacket_info_t;

    /*
     *  avpacketq_info:
     *  共享内存相关管理信息数据结构
     *
    */
    typedef struct avpacketq_info avpacketq_info_t;

    /*
    * avpacket_queue:
    * 编码数据包队列数据结构
    *
    */
    typedef struct avpacket_queue
    {
        char* name;
        int shmem_fd;
        uint32_t max_count;
        uint32_t avpacket_size;
        uint32_t max_size; // max_count * avpacket_size
        uint32_t mmap_size; // avpacketq_info_t + encoder_extra_data_size + max_size;
        avpacketq_info_t* mem; // 共享内存地址
    } avpacketq_t;

    /*
     * 函数说明：
     *     基于共享内存创建视频流编码队列
     * 参数说明：
     *     name：共享内存队列名，在系统中要唯一
     *     size：视频流包的大小
     * 返回说明：
     *     avpacket_queue_t: 返回新建的视频流编码队列对象
     *
    */
    avpacketq_t* avpacketq_new(char const* name, int count, uint32_t avpacket_size);

    /*
     * 函数说明：
     *     将编码器编码好的视频流数据包放入视频编码队列
     * 参数说明：
     *     self：视频编码队列对象
     *     buffer_in：avpaket_info_t + 编码好的视频流数据
     *     in_len: 编码好的视频流数据长度
     * 返回说明：
     *     int: 返回实际放入视频编码队列的数据长度
     *
    */
    int avpacketq_enqueue(avpacketq_t* self, avpacket_info_t* avpacket_info);

    /*
     * 函数说明：
     *     从视频编码队列获取视频流数据；首次使用初始化为 将 rd_index = -1
     * 参数说明：
     *     self：视频编码队列对象
     *     buffer_out：用于存放 avpaket_info_t + 视频编码数据包
     *     out_len: buffer_out 输出缓冲数据内存大小
     * 返回说明：
     *     int: 返回实际从视频编码队列取出的数据长度
     *
    */
    int avpacketq_dequeue(avpacketq_t* self, avpacket_info_t* avpacket_info);

    /*
     * 函数说明：
     *     销毁基共享内存创建的视频流编码队列
     * 参数说明：
     *     self：视频编码队列对象
     *     unlink：是否正销毁共享内存链接,默认输入0
     * 返回说明：
     *     无
     *
    */
    void avpacketq_destroy(avpacketq_t** self, int unlink);

    int avpacketq_set_encoder_info(avpacketq_t* self, encoder_info_t* encoder_info);

    int avpacketq_get_encoder_info(avpacketq_t* self, encoder_info_t* encoder_info);

#ifdef __cplusplus
}
#endif

#endif